﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace DM4Script
{
    public partial class ScriptParse
    {
        private Prototypes.ExprAst ParsesCommands()
        {
            if (_curTok != '{')  // has one command
                return ParsesCommand();
            
            var commands = new Queue<Prototypes.ExprAst>();

            GetNextToken();
            if (_curTok != '}')
            {
                while (true)
                {
                    Prototypes.ExprAst command = ParsesCommand();
                    if (command == null) return null;
                    commands.Enqueue(command);

                    if (_curTok == '}') break;
                }
            }
            GetNextToken();

            return new Prototypes.CommAndStask(commands);
        }

        private Prototypes.ExprAst ParsesCommand()
        {
            Prototypes.ExprAst command;

            if (_curTok != (char)Token.Identifier)
                return Error("Expected TASK, SUBTASK or COMMAND name in prototype");

            string taskName = _identifierStr.ToUpperInvariant();

            if (ScriptConst.command.Contains(taskName))
            {
                if (!String.IsNullOrEmpty(_propertyStr))
                    return Error(String.Format("Command name '{0}.{1}' is not bad", _identifierStr, _propertyStr));

                command = new Prototypes.Command(taskName);
            }
            else
            {
                //проверка на наличие task и property
                if (!Declare.Tasks.ContainsKey(taskName))
                    return Error(String.Format("ScriptTask name '{0}' is not declare", taskName));

                command = Declare.Tasks[taskName];
            }

            GetNextToken();

            if (_curTok != ';')
                return Error("Expected ';' in prototype");

            GetNextToken();

            return command;
        }

        private Prototypes.ExprAst ParsesProperty(IEnumerable<string> taskExists)
        {
            string taskName = _identifierStr.ToUpperInvariant();

            if (ScriptConst.command.Contains(taskName))
            {
                if (!String.IsNullOrEmpty(_propertyStr))
                    return Error(String.Format("Command name '{0}.{1}' is not bad", _identifierStr, _propertyStr));

                return new Prototypes.Command(taskName);
            }

            
            //проверка на наличие task и property
            if (!taskExists.Any(task => task == taskName))
                return Error(String.Format("ScriptTask name '{0}' is not declare", taskName));

            //property
            if (_propertyStr == null)
                return Error("Expected property task");

            string propertyName = _propertyStr.ToUpperInvariant();
            if (!ScriptConst.propertyDefault.Contains(propertyName))
                return Error(String.Format("Property name '{0}' is not declare", propertyName));

            Prototypes.ExprAst property = new Prototypes.Property(taskName, propertyName);
            GetNextToken();
            return property;
        }
    }
}
